#pragma once
#include "Common.h"

namespace kele
{
	// 大于128KB的需要另处理
	static const size_t sizeof_ptr = sizeof(void*); // 指针长度

	template<class T>
	class blockectPool
	{
	public:
		blockectPool() : _memory(nullptr), _freelist(nullptr), _remainder_size(0), _sizeof_T(sizeof(T))
		{
			if (_sizeof_T > _sysallocsize)
				_sysallocsize = 4 * _sizeof_T;
		}

		T* New()
		{
			T* newalloc = nullptr;
			// 如果回收空，就从开的空间拿
			if (_freelist)
			{
				newalloc = (T*)_freelist;
				_freelist = *(void**)_freelist;
			}
			else // 新开的空间拿
			{
				if (_sizeof_T > _remainder_size)// 空间不足
				{
					_remainder_size = _sysallocsize;
					// _memory = (char*)malloc(_remainder_size);
					_memory = (char*)SystemAlloc(_remainder_size >> PAGE_SHIFT);
				}
				size_t blocksize = _sizeof_T > sizeof_ptr ? _sizeof_T : sizeof_ptr;
				newalloc = (T*)_memory;
				_memory += blocksize;
				_remainder_size -= blocksize;
			}
			// 显示调用自定义类型的默认构造
			new(newalloc)T;

			return newalloc;
		}

		void Delete(T* block)
		{
			// 显示调用自定义类型的析构
			block->~T();

			// 头插
			// block的头sizeof_ptr字节是存放next的地址
			// *(void**)block
			*(void**)block = _freelist;
			_freelist = block;
		}
		
		std::mutex _mtx;

	private:
		char* _memory;			 // 开的空间块
		void* _freelist;		 // 回收的空间块单链表
		size_t _remainder_size;	 // memory剩余空间大小
		size_t _sizeof_T;
		size_t _sysallocsize = 128 * 1024;
	};
}
